#自写模块
import Read_data
import PCAprocess
import SVRProcess
import LSTMProcess
import Write_data
#python自带模块
import numpy as np 
import matplotlib.pyplot as plt
from sklearn.metrics import r2_score, mean_squared_error, mean_absolute_error
from math import sqrt

class Main:
    def __init__(self,filename='data_siguniangshan.xlsx'):
        self.filename=filename
        self.all_feature=[]
        self.all_flow_label=[]
        self.svr_predict=[]
        self.svr_flow=[]
        self.lstm_feature_weather=[]
        self.lstm_ratio=0.5
        self.svr_ratio=0.5
        self.final_flow_hat=[]
        self.final_flow_real=[]
        self.lstm_process=0
        self.loop_parameter_r2={}

        self.mainProcess()


    #main函数
    def mainProcess(self):
        #读13个搜索指数
        rd_baidu_feature=Read_data.Read_data(self.filename,1,13)
        baidu_feature=rd_baidu_feature.outputdata
        #pca降维
        pca_process=PCAprocess.PCAprocess(baidu_feature,3)
        pca_data=pca_process.output_data
        #读其他特征
        rd_other_feature=Read_data.Read_data(self.filename,14,14)
        other_feature=rd_other_feature.outputdata
        #读客流标签数据
        rd_flow_label=Read_data.Read_data(self.filename,24,24)
        flow_label=rd_flow_label.outputdata
        #数据合并
        self.all_feature=np.hstack((pca_data,other_feature))
        self.all_flow_label=flow_label
        #svr处理
        svr_process=SVRProcess.SVRProcess(self.all_feature,self.all_flow_label,self.svr_ratio,'linear')
        self.svr_predict=svr_process.y_hat_real
        self.svr_flow=svr_process.y_test_real

        #残差和svr的预测
        excel_redsidu=self.svr_flow-self.svr_predict
        excel_hatflow=self.svr_predict
        excel_redsidu=np.array(excel_redsidu)
        excel_hatflow=np.array(excel_hatflow)
        excel_hatflow=excel_hatflow.reshape((-1,1))
        excel_redsidu=excel_redsidu.reshape((-1,1))
        data_1=np.hstack((excel_redsidu,excel_hatflow))
        Write_data.Write_data("残差_svr预测图.xls",data_1)

        #lstm数据集生成
        rd_lstm_feature=Read_data.Read_data(self.filename,15,23)
        self.lstm_feature_weather=rd_lstm_feature.outputdata
        #截取特征长度
        len_feature=len(self.svr_flow)
        self.lstm_feature_weather=self.lstm_feature_weather[-len_feature:]


        self.lstm_label_residual=self.svr_flow-self.svr_predict
        ii=[30,40,50,60,70,75,80,85,90,100,110,120,130,140,150,200,300,600]
        jj=[40,60,70,80,130,200]
        for i in ii:
            for j in jj:
                #lstm处理
                self.lstm_process=LSTMProcess.LSTMProcess(self.lstm_feature_weather,self.lstm_label_residual,self.lstm_ratio,i,j)
                #最终评估指标所需数据处理
                self.estimate_dataprocess()
                #计算并输出评估指标
                self.estimate_final()
                # #画出最终效果图
                # self.plot_final()

                #生成轮次_最终r2_LSTMr2字典
                b=[]
                b.append(str(i))
                b.append(str(j))
                #将列表转为—连接的字符串
                c="-".join(b)
                a=[]
                a.append(r2_score(self.final_flow_real,self.final_flow_hat))
                a.append(self.lstm_process.estimate_lstm())
                self.loop_parameter_r2[c]=a
        print(self.loop_parameter_r2)
        #总列表初始化
        all_r2=[]
        for key,value in self.loop_parameter_r2.items():
            all_r2.append(key)
            all_r2.append(value[0])
            all_r2.append(value[1])
        
        all_r2=np.array(all_r2)
        all_r2=all_r2.reshape((int(len(all_r2)/3),3))
        print(all_r2)
        Write_data.Write_data("两个参数_最终r2_LSTMr2.xls",all_r2)


    #最终评估指标所需数据处理
    def estimate_dataprocess(self):
        n=len(self.lstm_feature_weather)-1 #数据的行数，转监督学习时损失一行
        len_train=self.lstm_process.len_train_number  #向下取整，训练集长度
        len_test=self.lstm_process.len_test_number #测试集长度
        #得到真正的客流test集
        lstm_flow=self.svr_flow[:]#残差剪了头（因为没有第一天的历史客流），所以该客流也要剪头。
        lstm_use_flow=lstm_flow[1:]#lstm转监督学习函数时会因为NAN损失第一行，再剪头
        lstm_test_flow_real=lstm_use_flow[len_train:]#取出真正预测的flow集：0.5，0.5时应该时379
        #得到最终使用的残差
        residuals_hat=self.lstm_process.y_hat_real#lstm预测的残差
        #得到svr预测的客流并且最终使用的test集
        lstm_flow_hat=self.svr_predict[:]
        lstm_use_flow_hat=lstm_flow_hat[1:]
        lstm_test_flow_svrhat=lstm_use_flow_hat[len_train:]

        
        self.final_flow_real=lstm_test_flow_real
        self.final_flow_hat=[]
        for i in range(0,len(residuals_hat)):
            self.final_flow_hat.append(residuals_hat[i]+lstm_test_flow_svrhat[i])
        self.final_flow_hat=list(self.final_flow_hat)
    
    #画图
    def plot_final(self):
        r = len(self.final_flow_real) + 1
        plt.plot(np.arange(1,r), self.final_flow_hat, 'r-', label="final_predict")
        plt.plot(np.arange(1,r), self.final_flow_real, '-', label="true_flow")
        plt.legend(loc='upper right')
        plt.show()

    #评估指标
    def estimate_final(self):
        # 对线性核函数模型评估
        print("组合模型决定系数(r方，R_squared)值为：", r2_score(self.final_flow_real,self.final_flow_hat))
        # 计算RMSE
        rmse = sqrt(mean_squared_error(self.final_flow_real, self.final_flow_hat))
        print('组合模型均方根误差(RMSE,Root Mean Square Error): ',rmse)
        print("组合模型均方误差(MSE, mean squared error)为:", mean_squared_error(self.final_flow_real,self.final_flow_hat))
        print("组合模型平均绝对值误差(MAE,mean_absolute_error)为:", mean_absolute_error(self.final_flow_real,self.final_flow_hat))


Main('data_jiuzhaigou.xlsx')